package cn.com.open.opensaas.scoreservice.controller.interceptor;

import cn.com.open.opensaas.scoreservice.domain.OperateLogModel.OperateDescription;
import cn.com.open.opensaas.scoreservice.domain.OperateLogModel.OperateLog;
import cn.com.open.opensaas.scoreservice.service.OperateLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.NamedThreadLocal;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * Created by lucky on 2017/7/21.
 */

/**
 * 操作日志AOP类
 */
@Aspect
@Component
@Order(-2)
public class ApiLogAspect {
    private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(ApiLogAspect.class);

    private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<>("StopWatch-StartTime");
    private NamedThreadLocal<OperateDescription> operateDescriptionThreadLocal = new NamedThreadLocal<>("loginfo");
    @Autowired
    OperateLogService service;

    /**
     * Web log.
     */
    @Pointcut("@annotation(cn.com.open.opensaas.scoreservice.controller.interceptor.Log)")
    public void webLog() {
        return;
    }

    /**
     * Do before.
     *
     * @param joinPoint the join point
     * @param log       the log
     * @throws Throwable the throwable
     */
    @Before("@annotation(log)")
    public void doBefore(JoinPoint joinPoint, Log log) {
        try {
            // 接收到请求，记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            //线程绑定变量（该数据只有当前请求的线程可见）
            startTimeThreadLocal.set(System.currentTimeMillis());

            OperateDescription operateDescription =OperateDescription.getDescriptionInfo(
                    joinPoint.getSignature().getDeclaringTypeName(),
                    joinPoint.getSignature().getName(),
                    joinPoint.getArgs(),
                    log,
                    request);
            operateDescriptionThreadLocal.set(operateDescription);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }


    /**
     * Do after returning.
     *
     * @param ret the ret
     * @throws Throwable the throwable
     */
    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) {
        try {
            // 处理完请求，返回内容
            //3、消耗的时间
            long consumeTime = System.currentTimeMillis() - startTimeThreadLocal.get();

            service.saveLog(operateDescriptionThreadLocal.get(), consumeTime);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }


}
